package com.base.cn.platform.os.service.op.coupon;

import com.base.cn.platform.os.common.msg.WXTmpEnum;
import com.base.cn.platform.os.common.mybatis.BaseBiz;
import com.base.cn.platform.os.common.mybatis.Pagination;
import com.base.cn.platform.os.common.utils.DataUtil;
import com.base.cn.platform.os.common.utils.DateUtils;
import com.base.cn.platform.os.common.utils.ObjectUtils;
import com.base.cn.platform.os.common.utils.StringUtils;
import com.base.cn.platform.os.common.utils.coupon.CouponConditions;
import com.base.cn.platform.os.dao.op.coupon.OpCouponCodeDao;
import com.base.cn.platform.os.entity.op.activity.OpActivity;
import com.base.cn.platform.os.entity.op.coupon.*;
import com.base.cn.platform.os.service.op.activity.OpActivityBiz;
import com.base.cn.platform.os.service.op.affiche.tmp.SendMessage;
import com.base.cn.platform.os.service.user.user.CusUserBiz;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 优惠编码Biz
 * Created by ll on 2017/7/14 0014.
 */
@Service
public class OpCouponCodeBiz extends BaseBiz<OpCouponCode,OpCouponCodeDao> {

    @Autowired
    private CusUserBiz cusUserBiz;
    @Autowired
    private OpCouponBiz opCouponBiz;
    @Autowired
    private OpUserBirthdayCodeBiz opUserBirthdayCodeBiz;
    @Autowired
    private OpUserCourseOpenCodeBiz opUserCourseOpenCodeBiz;
    @Autowired
    private OpUserActivityCodeBiz opUserActivityCodeBiz;
    @Autowired
    private OpActivityBiz opActivityBiz;
    @Autowired
    private OpCouponCodeDao opCouponCodeDao;
    @Autowired
    private SendMessage sendMessage;

    /**
     * 修改订单中使用优惠券时，修改优惠券编码状态
     * @param codeId 优惠券ID
     * @param status 状态
     */
    @Async
    public void updateOrderUseCodeStatus(BigDecimal codeId,int status){
        this.updateCouponCodeStatus(codeId,status);
    }

    /**
     * 修改优惠券编码状态
     * @param codeId 优惠券编码ID
     * @param status 状态
     */
    public void updateCouponCodeStatus(BigDecimal codeId,int status){
        OpCouponCode oldCouponCode = this.findCouponCodeById(codeId,true);
        OpCouponCode couponCode = new OpCouponCode();
        couponCode.setStatus(status);
        if(status==5){
            couponCode.setUseTime(new Date());
        }
        this.updateByWhereSql(couponCode," id ="+ codeId);
        int codeNum = oldCouponCode.getCoupon().getCodeNum();
        int useCount = oldCouponCode.getCoupon().getUseCount();
        int invalidCount = oldCouponCode.getCoupon().getInvalidCount();
        Integer _status = oldCouponCode.getStatus();
        OpCoupon opCoupon = new OpCoupon();
        opCoupon.setId(oldCouponCode.getCouponId());
        if(status == 1){//正常
            opCoupon.setUseCount(useCount-1);
        }
        if(status == 3){//删除
            opCoupon.setCodeNum(codeNum-1);
            this.setCount(opCoupon,_status,useCount,invalidCount);
        }
        if(status == 5){//使用
            opCoupon.setUseCount(useCount+1);
        }
        opCouponBiz.updateById(opCoupon,"id");
    }

    /**
     * 更新优惠劵数量相关数据
     * @param opCoupon
     * @param _status
     * @param useCount
     * @param invalidCount
     */
    private void setCount(OpCoupon opCoupon, Integer _status, int useCount, int invalidCount) {
        if(_status == 4){
            opCoupon.setInvalidCount(invalidCount-1);
        }
        if(_status == 5){
            opCoupon.setUseCount(useCount-1);
        }
    }

    /**
     * 通过编码获取优惠券对象
     * @param code 优惠编码
     * @param couponData 是否设置优惠券数据对象
     * @return OpCouponCode
     */
    public OpCouponCode findCouponCodeByCode(String code, boolean couponData) {
        OpCouponCode couponCode = new OpCouponCode();
        couponCode.setCode(code);
        String whereSql = this.whereSql(couponCode);
        OpCouponCode _couponCode = this.findOne(whereSql,null);
        if(couponData){
            _couponCode = this.setCouponByCouponCodeList(_couponCode);
        }
        return _couponCode;
    }

    /**
     * 通过ID，是查询优惠券编码
     * @param id
     * @param couponData
     * @return OpCouponCode
     */
    public OpCouponCode findCouponCodeById(BigDecimal id, boolean couponData) {
        OpCouponCode couponCode = this.findById(id);
        if(ObjectUtils.isNotEmpty(couponCode) && couponData){
            this.setCouponByCouponCodeList(couponCode);
        }
        return couponCode;
    }

    /**
     * 获取用户的优惠券列表
     * @param userId 用户ID
     * @return 优惠券列表
     */
    public List<OpCouponCode> queryUserCouponCodeListByUserId(BigDecimal userId,Integer status,boolean userName,boolean couponData) {
        if (DataUtil.idIsNotNull(userId)) {
            OpCouponCode opCouponCode = new OpCouponCode();
            opCouponCode.setUserId(userId);
            opCouponCode.setStatus(status);
            return this.queryUserCouponCodeList(opCouponCode,userName,couponData);
        }
        return null;
    }

    /**
     * 分页查询
     * @param page 分页
     * @param opCouponCode
     * @param userName
     * @param couponData
     * @return
     */
    public PageInfo<OpCouponCode> queryUserCouponCodeListPage(Pagination page,OpCouponCode opCouponCode,boolean userName,boolean couponData){
      String where = whereSql(opCouponCode);
        PageInfo<OpCouponCode> opCouponCodes = this.findPage(where,page,null);
        List<OpCouponCode> _opCouponCodes=setUserNameAndCouponList(opCouponCodes.getList(),userName,couponData);
        opCouponCodes.setList(_opCouponCodes);
        return opCouponCodes;
    }

    /**
     * 批量查询
     * @param opCouponCode
     * @param userName
     * @param couponData
     * @return
     */
    public List<OpCouponCode> queryUserCouponCodeList(OpCouponCode opCouponCode,boolean userName,boolean couponData){
        String where = whereSql(opCouponCode);
        List<OpCouponCode> opCouponCodes = this.find(where,null,null);
        return setUserNameAndCouponList(opCouponCodes,userName,couponData);
    }

    /**
     * 批量添加扩展信息
     * @param opCouponCodes 优惠券编码列表
     * @param setCusUserData 是否设置用户数据
     * @param couponData 是否设置优惠券数据
     * @return List<OpCouponCode>
     */
    private List<OpCouponCode> setUserNameAndCouponList(List<OpCouponCode> opCouponCodes,boolean setCusUserData,boolean couponData){
        if (ObjectUtils.isNotEmpty(opCouponCodes)){
            if(setCusUserData){
                cusUserBiz.setUserData(opCouponCodes,setCusUserData);
            }
            if (couponData){
                opCouponCodes = this.setCouponByCouponCodeList(opCouponCodes);
            }
        }
        return opCouponCodes;
    }

    /**
     * 搜索优惠券编码
     * @param opCouponCode
     * @return
     */
    public String whereSql(OpCouponCode opCouponCode){
        StringBuilder where = new StringBuilder(" 1=1 ");
        if(ObjectUtils.isNotEmpty(opCouponCode)){
            if(DataUtil.idIsNotNull(opCouponCode.getUserId())){
                where.append(" and  userId = ").append(opCouponCode.getUserId());
            }
            if(DataUtil.idIsNotNull(opCouponCode.getCouponId())){
                where.append(" and couponId =").append(opCouponCode.getCouponId());
            }
            if (DataUtil.idIsNotNull(opCouponCode.getOrderId())){
                where.append(" and orderId =").append(opCouponCode.getOrderId());
            }
            if (StringUtils.isNotEmpty(opCouponCode.getCode())){
                where.append(" and code = '"+opCouponCode.getCode().trim()).append("'");
            }
            if(StringUtils.isNotEmpty(opCouponCode.getOrderNo())){
                where.append(" and orderNo ='"+opCouponCode.getOrderNo().trim()).append("'");
            }
            if (ObjectUtils.isNotEmpty(opCouponCode.getEndTime())){
                where.append(" and endTime<'"+ DateUtils.format(opCouponCode.getEndTime(), "yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if (ObjectUtils.isNotEmpty(opCouponCode.getBeginUseTime())){
                where.append(" and useTime>='"+ DateUtils.format(opCouponCode.getBeginUseTime(), "yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if (ObjectUtils.isNotEmpty(opCouponCode.getEndUseTime())){
                where.append(" and useTime<='"+ DateUtils.format(opCouponCode.getEndUseTime(), "yyyy-MM-dd HH:mm:ss")).append("'");
            }
            if(DataUtil.isPositive(opCouponCode.getType())){
                where.append(" and type = ").append(opCouponCode.getType());
            }
            Integer status=opCouponCode.getStatus();
            if(status==null||status==0){
                where.append(" and status!=3");
            }else{
                where.append(" and status=").append(status);
            }
            if(ObjectUtils.isNotEmpty(opCouponCode.getSource()) && opCouponCode.getSource()==1){
                where.append(" and status!=2 and status!=4");
            }
            where.append(" ORDER BY status,updateTime desc");
        }
        return where.toString();
    }

    /**
     * 特定条件的搜索礼品卡
     * @param status
     * @param userId
     * @param count
     * @return
     */
    public List<OpCouponCode> queryOpCouponCodeByGiftCardIdAndStatusAndIsUserData(BigDecimal couponId, Integer status, BigDecimal userId, Integer count){
        StringBuilder whereSql = new StringBuilder();
        whereSql.append(" status =").append(status);
        if (DataUtil.idIsNotNull(couponId)){
            whereSql.append(" and couponId =").append(couponId);
        }
        if (DataUtil.idIsNotNull(userId)){
            whereSql.append(" and userId=").append(userId);
        }else{
            whereSql.append(" and (userId is  null or userId =0)");
        }
        return this.find(whereSql.toString(),count,null);
    }

    /**
     * 添加优惠券信息
     *
     * @param couponCode
     */
    public OpCouponCode setCouponByCouponCodeList(OpCouponCode couponCode){
        if(ObjectUtils.isNotEmpty(couponCode)){
            List<OpCouponCode> couponCodeList = new ArrayList<>();
            couponCodeList.add(couponCode);
            this.setCouponByCouponCodeList(couponCodeList);
            couponCode = couponCodeList.get(0);
        }
        return couponCode;
    }

    /**
     * 添加优惠券信息
     *
     * @param couponCodeList
     */
    public List<OpCouponCode> setCouponByCouponCodeList(List<OpCouponCode> couponCodeList) {
        if (ObjectUtils.isNotEmpty(couponCodeList)) {
            String couponIds = couponCodeList.stream().map(e -> e.getCouponId().toString()).distinct().collect(Collectors.joining(","));
            if (StringUtils.isNotEmpty(couponIds)) {
                List<OpCoupon> coupons = opCouponBiz.queryOpCouponByIds(couponIds,true,true,true,true);
                Map<BigDecimal, OpCoupon> couponMap = coupons.stream().collect(Collectors.toMap(OpCoupon::getId, e -> e));
                for (OpCouponCode couponCode : couponCodeList) {
                    if (couponMap.get(couponCode.getCouponId()) != null) {
                        couponCode.setCoupon(couponMap.get(couponCode.getCouponId()));
                    }
                }
            }
        }
        return couponCodeList;
    }

    /**
     * 个人中心专用搜索列表
     *
     * @param page   翻页
     * @param order  分组
     * @param status 优惠券状态
     * @param type 优惠券类型
     * @param userId 用户id
     */
    public PageInfo<OpCouponCode> queryUserCouponCode(Pagination page, Integer order, Integer status, Integer type, BigDecimal userId,boolean userName,boolean couponDate) {
        String whereSql = "1=1 and userId=" + userId;
        if (status!=null&&status>0) {
            if (status == 7) {
                whereSql += " and endTime <'" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()) + "' and status=1";
            } else if (status == 1) {
                whereSql += " and status=" + status + " and timeType=1 and endTime >= '" + DateUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss") + "' or (userId =" + userId + " and timeType=2 and status=" + status + ")";
            } else {
                whereSql += " and status=" + status;
            }
        } else {
            whereSql += " and status!=2 and status!=3 and status!=4";
        }
        if (type!=null&&type>0) {
            whereSql += " and type =" + type;
        }
        if (order!=null&&type>0) {
            whereSql += " order by createTime desc ";
        }
        PageInfo<OpCouponCode> pageInfo = this.findPage(whereSql,page, null);
        if (ObjectUtils.isNotEmpty(pageInfo.getList())) {
            List<OpCouponCode> couponCodes = pageInfo.getList();
            for (OpCouponCode couponCode :couponCodes) {
                if (couponCode.getStatus() == 1 && couponCode.getTimeType() == 1 && new Date().after(couponCode.getEndTime())) {
                    couponCode.setStatus(6);
                }
            }
            couponCodes =setUserNameAndCouponList(couponCodes,userName,couponDate);
            pageInfo.setList(couponCodes);
        }
        return pageInfo;
    }

    /**
     * 查询订单可用的优惠券（只用于存课程商品的订单）
     * @param paramsList 查询条件
     * @return List<OpCouponCode>
     */
    public List<OpCouponCode> findOrderAvailableCodeList(List<Map<String,String>> paramsList,BigDecimal userId){
        if(ObjectUtils.isNotEmpty(paramsList)){
            double price = paramsList.stream().mapToDouble(e->Double.parseDouble(e.get("price"))).sum();
            List<OpCouponCode> opCouponCodeList = queryUserAvailableCodeList(userId,price,paramsList);
            opCouponCodeList = this.setCouponByCouponCodeList(opCouponCodeList);
            return opCouponCodeList;
        }
        return null;
    }

    /**
     * 获取可以领取的优惠券编码
     * @param couponIds 优惠券ID串
     * @param userId 用户ID
     * @return List<OpCouponCode>
     */
    public List<OpCouponCode> findCouponCodeReceive(String couponIds,BigDecimal userId){
        Map<String,Object> params = new HashMap<>();
        params.put("couponIds",couponIds);
        params.put("userId",userId);
        return opCouponCodeDao.findCouponCodeReceive(OpCouponCode.class,params);
    }

    //=====================================================================
    /**
     * 赠送用户优惠券
     * @param userId 用户ID
     * @param conditions 获取条件，1手动发放，2新用户注册后自动获取，3学员生日获取，4邀请注册获取，5消费任意金额获取，6免费直播发放，7活动
     * @param count 获取数量(如果数量为0量，则获取该类型的所有的优惠券的各一张编码)
     */
    public List<OpCouponCode> giveUserCouponCode(BigDecimal userId,Integer[] conditions,int count){
        List<OpCouponCode> couponCodeList;
        if(count <=0){
            String _conditions = Arrays.stream(conditions).map(e->String.valueOf(e)).collect(Collectors.joining(","));
            couponCodeList = this.find(" (userId is null or userId =0) and conditions = "+_conditions+" and `status`=1 group by couponId,conditions",null,null);
        }else{
            couponCodeList = this.find(" (userId is null or userId =0) and conditions = "+conditions[0]+" and `status`=1",count,null);
        }
        if(ObjectUtils.isNotEmpty(couponCodeList)){
            String ids = couponCodeList.stream().map(e->e.getId().toString()).collect(Collectors.joining(","));
            OpCouponCode couponCode = new OpCouponCode();
            couponCode.setUserId(userId);
            this.updateByWhereSql(couponCode," id in ("+ids+")");

            //发送消息
            Map<BigDecimal,List> dataListMap = new HashMap<>();
            dataListMap.put(userId,couponCodeList);
            sendMessage.sendMessage(WXTmpEnum.COUPON_CODE,Arrays.asList(userId),dataListMap);
        }
        return couponCodeList;
    }

    /**
     * 赠送用户优惠券
     * @param userId 用户ID
     * @param conditions 获取条件，1手动发放，2新用户注册后自动获取，3学员生日获取，4邀请注册获取，5消费任意金额获取，6免费直播发放，7活动
     * @param count 获取数量(如果数量为0量，则获取该类型的所有的优惠券的各一张编码)
     */
    public List<OpCouponCode> giveUserCouponCode(BigDecimal userId,int conditions,int count){
        return this.giveUserCouponCode(userId,new Integer[]{conditions},count);
    }

    /**
     * 赠送用户优惠券
     * @param userId 用户ID
     * @param conditions 获取条件，1手动发放，2新用户注册后自动获取，3学员生日获取，4邀请注册获取，5消费任意金额获取，6免费直播发放，7活动
     */
    public List<OpCouponCode> giveUserCouponCode(BigDecimal userId,int conditions){
        return this.giveUserCouponCode(userId,new Integer[]{conditions},0);
    }

    /**
     * 新用户注册后赠送优惠券
     * @param userId 用户ID
     */
    @Async
    public void giveUserRegCouponCode(BigDecimal userId){
        this.giveUserCouponCode(userId, CouponConditions.TYPE_2);
    }

    /**
     * 用户注册赠送优惠券
     * @param userId 用户ID
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    @Async
    public void giveUserBirthdayCode(BigDecimal userId){
        boolean status = opUserBirthdayCodeBiz.isGetUserBirthdayCode(userId);
        //如果用户未获取过当前生日优惠券
        if(!status){
            List<OpCouponCode> opCouponCodeList = this.giveUserCouponCode(userId, CouponConditions.TYPE_3);
            if(ObjectUtils.isNotEmpty(opCouponCodeList)){
                Map<BigDecimal,List<OpCouponCode>> opCouponCodeListMap = opCouponCodeList.stream().collect(Collectors.groupingBy(e->e.getCouponId()));
                List<OpUserBirthdayCode> birthdayCodeList = new ArrayList<>();
                opCouponCodeListMap.forEach((k,v)->{
                    OpUserBirthdayCode birthdayCode = new OpUserBirthdayCode();
                    birthdayCode.setUserId(userId);
                    birthdayCode.setCouponId(k);
                    birthdayCodeList.add(birthdayCode);
                });
                opUserBirthdayCodeBiz.batchSave(birthdayCodeList);
            }
        }
    }

    /**
     * 赠送用户参加免费直播直播赠送优惠券
     * @param userId 用户ID
     * @param openCourseId　免费直播ID
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    @Async
    public void giveUserCourseOpenCode(BigDecimal userId,BigDecimal openCourseId){
        boolean status = opUserCourseOpenCodeBiz.isGiveUserCourseOpenCode(userId,openCourseId);
        if(!status){
            List<OpCouponCode> couponCodeList = this.find(" `status`=1 and (userId is null or userId =0) and conditions="+CouponConditions.TYPE_6+" and openCourseIds like '%,"+openCourseId+",%' group by couponId",null,null);
            if(ObjectUtils.isNotEmpty(couponCodeList)){
                OpUserCourseOpenCode openCode = new OpUserCourseOpenCode();
                openCode.setUserId(userId);
                openCode.setOpenCourseId(openCourseId);
                opUserCourseOpenCodeBiz.save(openCode);
            }
        }
    }

    /**
     * 用户消费任意金额赠送优惠券
     * @param userId 用户ID
     */
    @Async
    public void giveUserConsumePrice(BigDecimal userId){
        this.giveUserCouponCode(userId, CouponConditions.TYPE_5);
    }

    /**
     * 用户参加活动赠送优惠券
     * @param userId 用户ID
     * @param activityId 活动ID
     */
    @Transactional(rollbackFor = IllegalArgumentException.class)
    @Async
    public void giveActivityUserCode(BigDecimal userId,BigDecimal activityId){
        boolean status = opUserActivityCodeBiz.isUserActivityCode(userId,activityId);
        if(!status){
            OpActivity activity = opActivityBiz.findById(activityId,null);
            //活动存在，且是满送类型的活动，
            if(ObjectUtils.isNotEmpty(activity) && activity.getActivityType().contains("2")){
                String couponIds = activity.getCouponIds();
                couponIds = StringUtils.subHeadTailString(couponIds,",");
                List<OpCouponCode> couponCodeList = new ArrayList<>();
                int couponCount = activity.getCouponCount();//每个优惠券赠送量
                if(StringUtils.isNotEmpty(couponIds)){
                    Arrays.stream(couponIds.split(",")).forEach(id->{
                        List<OpCouponCode> _couponCodeList = this.find(" `status`=1 and (userId is null or userId = 0) and couponId = "+id +" limit "+couponCount,null,null);
                        if(ObjectUtils.isNotEmpty(_couponCodeList)){
                            couponCodeList.addAll(_couponCodeList);
                        }
                    });
                }
                if(ObjectUtils.isNotEmpty(couponCodeList)){
                    String ids = couponCodeList.stream().map(e->e.getId().toString()).collect(Collectors.joining(","));
                    OpCouponCode couponCode = new OpCouponCode();
                    couponCode.setUserId(userId);
                    this.updateByWhereSql(couponCode," id in ("+ids+")");
                    OpUserActivityCode activityCode = new OpUserActivityCode();
                    activityCode.setUserId(userId);
                    activityCode.setActivityId(activityId);
                    opUserActivityCodeBiz.save(activityCode);
                }
            }
        }
    }

    /**
     * 获取用户在支付页面上可以使用的优惠券列表
     * @param userId 用户ID
     * @param shopPrice　商品总金额
     * @param paramList　商品ID，类型列表
     * @return List<OpCouponCode>
     */
    private List<OpCouponCode> queryUserAvailableCodeList(BigDecimal userId,
                                                         double shopPrice,
                                                         List<Map<String,String>> paramList){
        Map<String,Object> params = new HashMap<>();
        params.put("userId",userId);
        params.put("shopPrice",shopPrice);
        params.put("paramList",paramList);
        return opCouponCodeDao.queryUserAvailableCodeList(OpCouponCode.class,params);
    }
}
